<?php
/**
 * $Id: upload.php 1167 2014-06-19 12:25:28Z shrey $
 * 
 * This file can not be redistributed to anyone without the permission of Giga Promoters
 * Copyright 2005 - 2008, Giga Promoters
 * 						  608 Aggarwal Cyber Plaza
 *						  Netaji Subhash Place, Delhi - 110034
 *						  www.gigapromoters.com
 * 
 *
 * This is parent of parent class of a controller and should not be edited ever without permission.
 * @version 			$Rev: 1167 $
 * @lastModifiedBy		$LastChangedBy: shrey $
 * @lastChanged			$Date: 2014-06-19 17:55:28 +0530 (Thu, 19 Jun 2014) $
 * @copyright 			Giga Promoters (www.gigapromoters.com)
 * 
 */

/**
 * This behavior lets you easily upload files through forms.
 * Very useful while file uploading.
 *
 */
class UploadBehavior extends ModelBehavior 
{

	var $__defaultSettings = array(

	'field' => 'filename',

	'required'=>false,

	'empty'=>	true,

	'limitSize'=>array('validate'=>false,'max_size'=>'400kb'),
	
	'allowedMedia' => null,//set to specify generic to allow generic media type like image,video,text,zip
	'allowedMime' => array('image/jpeg', 'image/pjpeg', 'image/gif', 'image/png'),

	'allowedExt' => array('jpg','jpeg','gif','png'),

	'overwriteExisting' => false,

	'createDirectory' => true,

	'randomFilenames' => false,

	
	'dir' => '{WWW_ROOT}{DS}uploads',
	
	'nameCleanups' => array(
	'/&(.)(acute|caron|cedil|circ|elig|grave|horn|ring|slash|th|tilde|uml|zlig);/' => '$1', // strip all
	'decode' => true, // html decode at this point
	'/\&/' => ' and ', // Ampersand
	'/\+/' => ' plus ', // Plus
	'/([^a-z0-9\.-]+)/' => '_', // None alphanumeric
	'/\\_+/' => '_' // Duplicate sperators
	),
	'resolution'=>array(
		'min'=>array('x'=>null,'y'=>null),
		'max'=>array('x'=>null,'y'=>null),
	),
	'slug' => true,
	'slugField' => 'slug'
	);
	var $mediaTypes =  array('Image','Video','Audio','Zip','Doc','Text');
    const VALIDATE_KEY_PREFIX = "uploadValidateRule_";
	function setup(AppModel $model, $configs=array())
	{
		$defaultConfig = array(
								'required'=>false,
								//can be like 4 mb or 4mb or 500kb etc.
								'maxSize'=>false,
								//unset field from data while saving if field is empty.
								'removeOnEmpty' => true,
								'empty' => true,
								'removeOnDelete'=>true,
								'removeOnUpdate'=>true,
								'disallowedExtensions'=>false,
								'dir'=>WWW_ROOT.'uploads'.DS,'mediaTypes'=>array("Image"=>array()),
								//random or 
								'fileName'=>"random",
								'slugPath'=>false,
								'slugFunction'=>false,
								//false or else string of size like 400kb or 5MB etc.
								'overwrite'=>false,
								//if true no proeccessing will be done.
								'moveOnly'=>false,
								'createDirectory'=>true);
		if(is_string($configs))
		{
			$configs = array($configs);
		}
		$configToSet = array();
		foreach($configs as $field => $config)
		{
			if(is_numeric($field))
			{
				$field = $config;
				$config = array();
			}
			$configToSet = am($defaultConfig,$config);
			if(!isset($model->fieldProperties[$field]['type']))
			{
				$model->fieldProperties[$field]['type'] = "file";
			}
			foreach($configToSet['mediaTypes'] as $mediaType => $mediaConfig)
			{
				if(is_numeric($mediaType))
				{
					unset($configToSet['mediaTypes'][$mediaType]);
					$mediaType = $mediaConfig;
					$mediaConfig = array();
				}
				if($mediaType != "*")
				{
					$mediaConfig = am($this->getMediaTypeConfig($model,$mediaType),$mediaConfig);
				}
				$configToSet['mediaTypes'][$mediaType] = $mediaConfig;
			}
			$validationRuleFn = array("validMediaType",array_keys($configToSet['mediaTypes'])); 
			$validationRules = array();
			$validationRules[] = array('rule'=>$validationRuleFn,'message'=>sprintf(__("Please upload a valid %s file."),implode(" or ",array_keys($configToSet['mediaTypes']))));
			if(is_string($configToSet['maxSize']))
			{
				$msg = sprintf(__('Please upload file with size less than %s'),$configToSet['maxSize']);
				$validationRules[] = array('rule'=>array("validFileSize",$configToSet['maxSize']),'message'=>$msg);
			}
			if($configToSet['empty'] == false || $configToSet['required'] == true)
			{
				$validationRules[] = array('rule'=>"uploadNotEmpty",'required'=>$configToSet['required'],'message'=>__("This field is required."));
			}
            $validationRules[] = array('rule'=>"validateUploadErrors",'message'=>__("There is some problem in your upload.Please try again"));
			$keyedValidationRules = array();
            //add prefixes .So clean up can clean added rules.
            foreach($validationRules as $validationRule)
            {
              $validationKey = self::VALIDATE_KEY_PREFIX.rand(1,400);
              $newKey = null;
              if(is_string($validationRule['rule']))
              {
                  $newKey =  $validationRule['rule'];
              }else if(is_array($validationRule['rule']))
              {
                  $newKey =  $validationRule['rule'][0];
              }
              if($newKey)
              {
                $newKey = self::VALIDATE_KEY_PREFIX.low($newKey);
              }
              if($newKey && !isset($keyedValidationRules[$newKey]))
              {
                  $validationKey = $newKey;
              }
              $keyedValidationRules[$validationKey] = $validationRule;
            }
            $model->addValidationRule($field,$keyedValidationRules);
			$this->settings[$model->alias][$field] = $configToSet;
		}
	}
     //clean rules added by the Behavior.
    function cleanup(AppModel $model)
    {
      //cleanUp Validation rules.
      //
      foreach($this->settings[$model->alias] as $field => $config)
      {
        if(isset($model->validate[$field]) && is_array($model->validate[$field]))
        {
          foreach($model->validate[$field] as $validationKey => $ruleArray)
          {
            if(is_array($ruleArray) && isset($ruleArray['rule']))
            {
                if( preg_match('/^'.  preg_quote(self::VALIDATE_KEY_PREFIX).'.+$/', $validationKey))
                {
                  unset($model->validate[$field][$validationKey]);
                }
            }
          }
        }
      }
    }
	
	private function getImageConfig()
	{

		$config = array('allowedMime'=>array('image/*'),
						'allowedExt'=>array('jpg','jpeg','gif','png','bmp'),
						//array('min'=>'x*y','max'=>'x*y')
						'resolution'=>false,
		);
		return $config;
	}
	
	private function getVideoConfig()
	{
		$config = array('allowedMime'=>array('video/*','application/octet-stream',"application/vnd.rn-realmedia"),
						'allowedExt'=>array('avi','flv','wmv','3gp','mp4','mpeg','mov',"rm","m4v"),
						'FFMPEG_PATH'=>false,
						'convertVideo' => true,
		);
		return $config;
	}
	
	private function getTextConfig()
	{
		$config = array("allowedMime"=>array("text/plain"),
						"allowedExt"=>array("txt"));
		return $config;
	}
	
	private function getDocumentConfig()
	{
		$config = array("allowedMime"=>array("text/plain","application/*"),
					"allowedExt"=>array("txt","doc","docx","pdf"));
		return $config;
	}
	
	function uploadNotEmpty($model,$data)
	{
		$notEmpty = true;
		$value = array_shift(array_values($data));
		if(!is_array($value) || !isset($value['name']) || strlen($value['name']) < 1)
		{
			$notEmpty = false;
		}
		return $notEmpty;
	}
    
    /**
     * Validate if file is upload it doesn't any error.Like Max file size.
     */
    function validateUploadErrors(AppModel $model,$data)
    {
      $field = array_shift(array_keys($data));
      $value = array_shift(array_values($data));
      $return = true;
      if(is_array($value) && isset($value['error']))
      {
          switch($value['error'])
          {
            case UPLOAD_ERR_PARTIAL:
              $return = __("File was partially uploaded.");
              break;
            case UPLOAD_ERR_INI_SIZE:
              $maxSize = ini_get("upload_max_filesize");
              $maxSize .= 'B';
              $maxSize = str_replace("MB"," MB",$maxSize);
              $return  = sprintf(__("File size is greater than allowed maximum file size of %s"),$maxSize);
              break;
          }
      }
      return $return;
    }
	/**
	 * 
	 * @param unknown_type $model
	 * @param unknown_type $data
	 * @param unknown_type $mediaTypes
	 */
	function validMediaType($model,$data,$mediaTypes)
	{
		$mediaTypes = (array)$mediaTypes;
		$valid = false;
		$field = array_shift(array_keys($data));
		$value = array_shift(array_values($data));
		//surpasses check if no upload.
		if(!is_array($value) || !$value['tmp_name'])
		{
			return true;
		}
		$fileName = $value['tmp_name'];
		$fileInfo = array("name"=>$value['name'],'mime'=>$value['type'],'file_path'=>$value['tmp_name']);
		$errorCount = 0;
		$lastFailError = false;
		$valueToReturn = false;
		$errorMsg = false;
		$errorMsgs = array();
		$mediaErrorMsg = false;
		if(!in_array("*",$mediaTypes))
		{
			foreach($mediaTypes as $mediaType)
			{
				$isValidMedia = $this->isMediaType($model,$mediaType,$field,$fileInfo);
				if($isValidMedia === true )
				{
					$validFunction = "valid".$mediaType;
					$validationResult = $model->$validFunction($field,$fileInfo);
					if($validationResult !== true)
					{
						$mediaErrorMsg = $validationResult;
					}else
					{
						$valueToReturn = true;
						break;
					}
				}else
				{
					$errorMsgs[] = $isValidMedia;
				}
			}
		}
		if($this->settings[$model->alias][$field]['disallowedExtensions'])
		{
			if($this->isExtensionPresent($value['name'],$this->settings[$model->alias][$field]['disallowedExtensions']))
			{
				$valueToReturn = false;
				$mediaErrorMsg = sprintf(__("Please upload a valid file. %s extensions are not allowed!"),implode(",",$this->settings[$model->alias][$field]['disallowedExtensions']));
			}else
			{
				$valueToReturn = true;;
			}
		}
		if($valueToReturn === false)
		{
			if($mediaErrorMsg)
			{
				$valueToReturn = $mediaErrorMsg;
			}
			//for single media type  case only.
			else if(count($errorMsgs) == 1)
			{
				$valueToReturn = $errorMsgs[0];
			}
		}
		return $valueToReturn;
	}
	/**
	 * 
	 * @param unknown_type $model
	 * @param unknown_type $field
	 * @param unknown_type $fileInfo
	 */
	function validImage($model,$field,$fileInfo)
	{
		$return = true; 
		if($return == true)
		{
			$resolution = $this->settings[$model->alias][$field]['mediaTypes']['Image']['resolution'];
			if(is_array($resolution))
			{
				$imageResolution  = array();
				$img = getimagesize($fileInfo['file_path']);
				if($img)
				{
					$imageResolution =  array('x'=>$img[0],'y'=>$img[1]);

					if(isset($resolution['max']))
					{
						if($resolution['max']['x'] < $imageResolution['x'] || $resolution['max']['y'] < $imageResolution['y'])
						{
							$return = sprintf(__("Please upload a image with resolution less than %s px. You uploaded: %s px"),$resolution['max']['x'].'x'.$resolution['max']['y'],$imageResolution['x'].'x'.$imageResolution['y']);
						}
					}else if(isset($resolution['min']))
					{
						if($resolution['min']['x'] > $imageResolution['x'] || $resolution['min']['y'] > $imageResolution['y'])
						{
							$return = sprintf(__("Please upload a image with resolution greater than %s px. You uploaded: %s px"),$resolution['min']['x'].'x'.$resolution['min']['y'],$imageResolution['x'].'x'.$imageResolution['y']);
						}
					}
				}
			}
			//check for other things.
		}
		return $return;
	}
	
	function validVideo($model,$field,$fileInfo)
	{	
		$return = true;
		return $return;
	}
	
	function validText($model,$fild,$fileInfo)
	{
		return true;
	}
	
	function validDocument($model,$fild,$fileInfo)
	{
		return true;
	}
	/**
	 * returns true or error Msg
	 * @param $mediaType
	 * @param $field
	 * @param $fileInfo
	 */
	function isMediaType($model,$mediaType,$field,$fileInfo)
	{
		$config = $this->getMediaTypeConfig($model,$mediaType,$field);
		$return = true;
		if($this->isExtensionPresent($fileInfo['name'],$config['allowedExt']) == false)
		{
			$return = sprintf(__("Please upload a %s with valid extension. Only .%s extensions are allowed"),__(low($mediaType)),implode(",",$config['allowedExt']));
		}else if($this->isValidMime($fileInfo['mime'],$config['allowedMime']) === false)
		{
			$return = sprintf(__("MIME type not allowed. A valid %s mime is required"),__(low($mediaType)));
		}
		return $return;
	}
	function isExtensionPresent($file,$extensions)
	{
		return $extensions == "*" || in_array(getExt($file),$extensions);
	}
	
	function isValidMime($mime,$mimeList)
	{
		$mimePart = explode('/',$mime);
		$mimeList = (array)$mimeList;
		$wildCards = array("*",low($mimePart[0]).'/*');
		return count(array_intersect($wildCards,$mimeList)) > 0 || in_array($mime,$mimeList);
	}
	
	private function getMediaTypeConfig(AppModel $model,$mediaType,$field = false)
	{
		$config = array();
		if($field !== false && isset($this->settings[$model->alias][$field]['mediaTypes'][$mediaType]))
		{
			$config = $this->settings[$model->alias][$field]['mediaTypes'][$mediaType];
		}else
		{
			$mediaTypeConfigFunction  = "get".$mediaType.'Config';
			$config = $this->$mediaTypeConfigFunction();
		}
		return $config;
	}
	
	function validFileSize(AppModel $model,$data,$size)
	{
		$field = array_shift(array_keys($data));
		$value = array_shift(array_values($data));
		if(!is_array($value))
		{
			return true;
		}
		$return = true;
		if($this->validateFileSize($value['size'],$size) == false)
		{
			$return = false;
		}
		return $return;
	}
	/**
	 * 
	 * @param unknown_type $fileSize
	 * @param unknown_type $sizeLimit can be like 3mb,500kb
	 */
	private function validateFileSize($fileSize,$sizeLimit)
	{
		$unit = low(substr($sizeLimit,-2));
		$size = substr($sizeLimit,0,strlen($sizeLimit)-2);
		$size = trim($size);
		$factor = 1;
		switch($unit)
		{
			case 'kb':
				$factor = 1;
                break;
			break;
			case 'mb':
				$factor = 2;
				break;
			case 'gb':
				$factor = 3;
				break;

		}
		//change from  bytes. and check
		$return = true;
        $maxSizeInBytes = $size* pow(1024,$factor);
		if($fileSize > $maxSizeInBytes)
		{
			$return = false;
		}
		return $return;
	}
	/**
	 * Handles the upload part. 
	 *
	 * @param unknown_type $source
	 * @param unknown_type $destination
	 * @return unknown
	 */
	function _processUpload($source, $destination)
	{
		if(is_uploaded_file($source)==true)
			return move_uploaded_file($source, $destination);
		else
			return copy($source,$destination);
	}

	/**
	 * add error handling if fails to create flv
	 *
	 * @param unknown_type $model
	 * @param unknown_type $dir
	 * @param unknown_type $filename
	 * @param unknown_type $extension
	 * @return unknown
	 */
	function processVideo($model, $fromFile, $toFile, $FFMPEG_PATH = null)
	{
		if(!$FFMPEG_PATH)
		{
			$FFMPEG_PATH = cr("cms.Upload.ffmpegPath");
		}
		$fromFileInfo = pathinfo($fromFile);
		$toFileInfo = pathinfo($toFile);
		$this->log('File name for processing: '.$fromFile, LOG_INFO);
		$rawFile = $fromFile;
		$tmpFile = $fromFileInfo['dirname'].DS.$fromFileInfo['filename'].'_temp.'.$fromFileInfo['extension'];
		rename($rawFile, $tmpFile); // renames temp. file so name doesnt mismatch with resultant file
		$rawFile = $tmpFile;
		$outputFile = $toFile;
		
		$thumb = $toFileInfo['filename'].'.jpg';
		$thumbFile = $toFileInfo['dirname'] .DS. $thumb;
		// process file to convert from normal video
		//$mov = &new ffmpeg_movie($rawFile);  // add error handline here
		$ex = $FFMPEG_PATH." -i ".$rawFile." -deinterlace -ar 44100 -ab 56000 -b 240k -qmin 6 -qmax 10 -f flv ".$outputFile;
		$this->log('Converting video.. (executing: '.$ex.')', LOG_INFO);
		exec($ex,$out);
		$this->log($ex."\n\n".print_r($out,true),"ffmpeg_exec");

		//generate video thumbs and store them in /attachments
		$fc=1;
		$ex=$FFMPEG_PATH." -i ".$outputFile;
		$ex=$ex." -f mjpeg -ss ".$fc;
		$ex=$ex." -vframes 1 -an ";
		$ex=$ex.$thumbFile;
		$this->log('Generating video thumb.. (executing: '.$ex.')', LOG_INFO);
		exec($ex);
		@unlink($tmpFile);
		return true;
	}
	
	/**
	 * Deletes the uploaded file and related thumbs.
	 *
	 * @param unknown_type $model
	 * @return unknown
	 */
	function beforeDelete(&$model) {
		
		$this->filesToDelete[$model->alias] = array();
		foreach($this->settings[$model->alias] as $field => $config)
		{
			if($config['removeOnDelete'] != false)
			{
				$this->filesToDelete[$model->alias] = am($this->filesToDelete[$model->alias],$this->getFilesToDelete($model,$field,$model->id));
			}
		}
		return true;
	}
	function afterDelete(AppModel $model)
	{
		if(isset($this->filesToDelete[$model->alias]))
		{
			foreach($this->filesToDelete[$model->alias]  as $file)
			{
				@unlink($file);
			}
			$this->filesToDelete[$model->alias] = array();
		}
		return true;
	}
	private function getFilesToDelete(AppModel $model,$field,$id)
	{
        //@todo use AppModel::field instead of AppModel::find once fix for Eav is found.
        //find used instead of field to fix problem in case of EAV.    
        $record = $model->find('first',array("conditions"=>array("id"=>$id),'recursive'=>-1));
		if(!isset($record[$model->alias][$field]))
        {
          return;
        }
        $fileName = $record[$model->alias][$field];
		$filePaths = array(); 
		if($fileName)
		{
			$config = $this->settings[$model->alias][$field];
			$uploadPath = $this->getUploadDir($config['dir']);
			$filePath = $uploadPath.DS.$fileName;
			$filePaths[] = $filePath;
			$mediaTypes = array_keys($config['mediaTypes']);
			$fileInfo =  pathinfo($filePath);
			if(in_array('Image',$mediaTypes) && strpos($filePath,WWW_ROOT.'uploads') !==false)
			{
				$fileRelativePath = str_replace(WWW_ROOT.'uploads','',$filePath);
				$fileUrl = str_replace(DS,'/',$fileRelativePath);
				$quotedDS = preg_quote(DS);
				if($quotedDS == "/")
				{
					$quotedDS = "\/";
				}
				$fileUrl = preg_replace("/($quotedDS+)/",'/',$fileUrl);
				require_once CMS_VENDORS_PATH.'thumbs.php';
				removeCachedThumbs($fileUrl);
				//new code added for cropped listing assets deletion - start-20140128
				$thumbImages = $this->getRecursiveFilePaths($uploadPath.DS."thumbs", $fileName, true);
				if(is_array($thumbImages) && !empty($thumbImages))
				{
					foreach($thumbImages as $thumbImageFilePath)
					{
						$filePaths[] = $thumbImageFilePath;
					}
				}
				//new code added for cropped listing assets deletion - end-20140128
			}
			if(in_array("Video",$mediaTypes) && $fileInfo['extension'] == "flv")
			{
				$filePaths[] = $uploadPath.DS.$fileInfo['filename'].'.jpg';
			}
		}
		return $filePaths;
	}

	function initDir(&$model, $dirToCheck = null) {

		extract($this->settings[$model->name]);
		if ($dirToCheck) {
			$dir = $dirToCheck;
		}

		// Check if directory exists and create it if required
		if(!is_dir($dir)) {
			if($create_directory && !$this->Folder->mkdirr($dir)) {
				unset($config[$field]);
				unset($model->data[$model->name][$field]);
			}
		}

		// Check if directory is writable
		if(!is_writable($settings['dir'])) {
			unset($config[$field]);
			unset($model->data[$model->name][$field]);
		}
		// Check that the given directory does not have a DS on the end

		if($settings['dir'][strlen($settings['dir'])-1] == DS) {
			$settings['dir'] = substr($settings['dir'],0,strlen($settings['dir'])-2);
		}
	}
	/**
		Returns intial name for the file
		It can return uuid , sluged form or name of uploaded file
		@todo Need refactoring.
	**/
	function _getFilename($model, $string) {

		extract ($this->settings[$model->name]);
		if(isset($slug) && $slug==true )
		{
			if($slugField=='')
				$string =null;
			else
				$string = Set::extract($model->data,$slugField);
			if(!$string)
			{
				if($model->name == 'Asset' &&  isset($model->data[$model->name]['item_id']) && isset($model->data[$model->name]['type']) && isset($model->{$model->data[$model->name]['type']}))
				{
					$displayField= $model->{$model->data[$model->name]['type']}->displayField;
					$string = $model->{$model->data[$model->name]['type']}->field($displayField,array('id'=>$model->data[$model->name]['item_id']));
					if(isset($model->{$model->data[$model->name]['type']}->actsAs['Cms.Upload']))
					{
						$string = $model->data[$model->name]['type'].'-'.$string;
					}
					$string = Inflector::slug($string);
				}
			}
			if(!$string)
			{
				$randomFilenames = true;
				$slug=false;
				$this->settings[$model->name];
			}else
				$randomFilenames = false;
		}
		if ($randomFilenames) {
			return uniqid("");
		}
		//disabled as per GigaCms #482
		//$string = htmlentities(low($string), null, 'UTF-8');
		//foreach ($nameCleanups as $regex => $replace) {
		//	if ($regex == 'decode') {
		//		$string = html_entity_decode($string);
		//	} else {
		//		$string = preg_replace($regex, $replace, $string);
		//	}
		//}
		if(isset($slug) && $slug==true)
			$string = $this->generateFileSlug($model,$string);
		return $string;
	}

	function _getPath ($model, $path) {

		extract ($this->settings[$model->name]);

		if (strpos($dir,'{') === false) {
			return $dir;
		}

		$markers = array('{APP}', '{DS}','{WWW_ROOT}');
		$replace = array( APP, DS, WWW_ROOT);
		$folderPath = str_replace ($markers, $replace, $path);

		new Folder ($folderPath, true);
		return $folderPath;

	}

	/**
	 * returns url path of the file
	 * @param unknown_type $model
	 * @param unknown_type $data
	 * @return unknown_type
	 */
	function fileName($model,$data)
	{
		if(isset($data[$model->alias][$this->settings[$model->name]['field']])==false)
			return;
		$file = $data[$model->alias][$this->settings[$model->name]['field']];
		if($file=='')
			return;
		$dirPath = $this->settings[$model->name]['dir'];
		$dirPath = str_replace('{WWW_ROOT}','',$dirPath);
		$urlPath = str_replace('{DS}','/',$dirPath);
		if($urlPath[0]!='/')
			$urlPath = '/'.$urlPath;
		return $urlPath;
	}

	function beforeSave(AppModel $model)
	{
		foreach($this->settings[$model->alias] as $field => $config)
		{
			$mediaTypesConfigs = $config['mediaTypes'];
			unset($config['mediaTypes']);
			if(isset($model->data[$model->alias][$field]) && (!is_array($model->data[$model->alias][$field]) || !$model->data[$model->alias][$field]['name']))
			{
				if($config['removeOnEmpty'])
				{
					unset($model->data[$model->alias][$field]); 	
				}else
				{
					$model->data[$model->alias][$field] = "";
				}
			}
			if(!isset($model->data[$model->alias][$field]) || is_string($model->data[$model->alias][$field]))
			{
				continue;
			}
			$fileInfo = array("name" => $model->data[$model->alias][$field]['name'],'mime'=>$model->data[$model->alias][$field]['type'],'file_path'=>$model->data[$model->alias][$field]['tmp_name']);
			$mediaTypeName = false;
			$allowAllMedia = in_array("*",array_keys($mediaTypesConfigs));
			foreach($mediaTypesConfigs as $mediaType => $mediaConfig)
			{
				if($mediaType == "*")
				{
					continue;
				}
				if($this->isMediaType($model,$mediaType,$field,$fileInfo))
				{
					$mediaTypeName = $mediaType;
					break;
				}
			}
			if($mediaTypeName || $allowAllMedia == true)
			{
				$fileName = $this->getFileName($model,$model->data,$field);
				try {
					//this should be completed path to saved file.
					$filePath = $this->proccessUpload($model,$fileInfo,$field,$mediaTypeName,$fileName);
				}catch(UploadProccessException $e)
				{
					$this->log($e->getMessage(),"failupload");
					$model->invalidate($field,$e->getMessage());
					return false;
				}
				$fileInfo = pathinfo($filePath);
				$model->data[$model->alias][$field.'_uploadInfo'] = array('filename'=>$model->data[$model->alias][$field]['name'],"fullpath"=>$filePath,'mediaType'=>$mediaType,'size'=>$model->data[$model->alias][$field]['size'],'mime'=>$model->data[$model->alias][$field]['type']);
				$model->data[$model->alias][$field] = basename($filePath);
			}
		}
		return true;
	}
	private function proccessUpload($model,$fileInfo,$field,$mediaTypeName,$fileName)
	{
		$config = $this->settings[$model->alias][$field];
		$uploadPath = $this->getUploadDir($config['dir']);
		if(!is_dir($uploadPath))
		{
			if($config['createDirectory'])
			{
				mkdir($uploadPath,0777);
			}	
		}
		if(!is_dir($uploadPath) || !is_writable($uploadPath))
		{
			throw new UploadProccessException(__($uploadPath." path not found.or path is not writable"));
		}
		if($mediaTypeName && $config['moveOnly'] === false)
		{
			$processFunction = "process".$mediaTypeName.'Upload';
			$ext = getExt($fileInfo['name']);
			$fileToSave = $fileName.'.'.$ext;
			//$uploadPath is upload dir,$fileToSave is fine name
			$fileSavedPath = $model->$processFunction($field,$fileInfo,$uploadPath,$fileToSave);
		}else
		{
			$filePathInfo =  pathinfo($fileInfo['name']); 
			$uploadFile = $uploadPath.DS.$fileName;
			if(isset($filePathInfo['extension']) && $filePathInfo['extension'])
			{
				$uploadFile .= '.'.$filePathInfo['extension'];
			}
			$this->moveFile($fileInfo['file_path'],$uploadFile);
			$fileSavedPath = $uploadFile;
		}
		return $fileSavedPath;
	}
	function processVideoUpload($model,$field,$fileInfo,$uploadPath,$fileName)
	{
		$uploadFile = $uploadPath.DS.$fileName; 
		$this->moveFile($fileInfo['file_path'],$uploadFile);
		if($this->settings[$model->alias][$field]['mediaTypes']['Video']['convertVideo'])
		{
			$newPath = $uploadFile.'.flv';
			if(file_exists($newPath))
			{
				$fileInfo = pathinfo($uploadFile);
				$newFileName = $fileInfo['filename'].'_'.time().'.'.$fileInfo['extension'];
				$newPath = $fileInfo['dirname'].DS.$newFileName;
			}
			$this->processVideo($model,$uploadFile,$newPath,$this->settings[$model->alias][$field]['mediaTypes']['Video']['FFMPEG_PATH']);
		}else
		{
			$newPath = $uploadFile;
		}
		return $newPath;
	}
	function processImageUpload($model,$field,$fileInfo,$uploadPath,$fileName)
	{
		$uploadFile = $uploadPath.DS.$fileName; 
		$uploadFile = $this->moveFile($fileInfo['file_path'],$uploadFile);
		return $uploadFile;
	}
	
	function processTextUpload($model,$field,$fileInfo,$uploadPath,$fileName)
	{
		$uploadFile = $uploadPath.DS.$fileName; 
		$uploadFile = $this->moveFile($fileInfo['file_path'],$uploadFile);
		return $uploadFile;
	}
	function processDocumentUpload($model,$field,$fileInfo,$uploadPath,$fileName)
	{
		$uploadFile = $uploadPath.DS.$fileName; 
		$uploadFile = $this->moveFile($fileInfo['file_path'],$uploadFile);
		return $uploadFile;
	}
	private function moveFile($from,$toPath)
	{
		if(file_exists($toPath))
		{
			$fileName = basename($toPath);
			$ext = getExt($fileName);
			$extSafe = preg_quote($ext);
			$fileName = preg_replace("/\.$extSafe$/","",$fileName);
			$fileName = $fileName.'_'.time().'.'.$ext;	
			$toPath = dirname($toPath).DS.$fileName;	
		}
		if(is_uploaded_file($from))
		{
			$return =  move_uploaded_file($from ,$toPath);
		}else
		{
			$return = copy($from ,$toPath);
		}
		if($return == false)
		{
			throw new UploadProccessException("Not able to copy file form $from to $toPath");
		}
		return $toPath;
	}
	private function getUploadDir($dir)
	{
		$markers = array('{APP}', '{DS}','{WWW_ROOT}');
		$replace = array( APP, DS, WWW_ROOT);
		$folderPath = str_replace ($markers, $replace, $dir);
		return $folderPath;
	}
	protected function getFileName($model,$data,$field)
	{
		$config = $this->settings[$model->alias][$field];
		$fileName = null;
		if($config['slugFunction'] && is_string($config['slugFunction']))
		{
			$fileName = $model->$config['slugFunction']($data,$field);
		}else if($config['slugPath'])
		{
			$fileName = Set::extract($config['slugPath'],$data);
			$fileName = $this->generateSlug($model,$field,$fileName);
		}
		if(!$fileName)
		{
			$fileName = $this->generateRandomFileName();
		}
		return $fileName;
	}
	private function generateRandomFileName()
	{
		return uniqid("");
	}
	private function generateSlug(AppModel $model,$field,$fileName)
	{
		$slug = Inflector::slug($fileName,'_');
		$count = $model->find('count',array("conditions"=>array($model->alias.'.'.$field." like" => $slug."_%"))); 		
		if( $count)
		{
			$slug .= "_".++$count;
		}
		return $slug; 
	}
	function _uncompress($model, $file, $extractTo)
	{
		extract($this->settings[$model->name]);
		$model->zipObj = new ZipArchive();
		$model->zipObj->open($file);
		
		if(!$model->{$zipValidation}())
		{
			return false;
		}
		// I hate this part right here
		$extractTo = str_replace('{WWW_ROOT}','',$extractTo);
		$extractTo = str_replace('{DS}','/',$extractTo);
		
		if($model->zipObj->extractTo($extractTo))
		{
			return true;
		}
		return false;
	}
	//new function added for cropped listing assets deletion - start-20140128
	protected function getRecursiveFilePaths($filepath, $filename=null, $returnList = false) 
	{
		$filePaths = array();
		$sourceFolder = is_dir(realpath($filepath)) ? realpath($filepath) : dirname(realpath($filepath));
		$sourceFilename = basename(realpath($filepath));
		
		$dir_handle = opendir($sourceFolder);
		if (!$dir_handle)
		{
			return false; //will not recurse unless base file $filepath exists
		}
		while ($file = readdir($dir_handle))
		{
			if ($file == '.' || $file == '..')
			{
				continue;
			}
			$filenameToMatch = ($filename ? basename($filename) : $sourceFilename);
			if (is_file($sourceFolder . '/' . $file))
			{
				if ($file === $filenameToMatch) {
					if($returnList)
					{
						$filePaths[] = $sourceFolder . '/' . $file;
					} else {
						unlink($sourceFolder . '/' . $file); //delete file
					}
				}
			} else {
				$subDirFiles = $this->getRecursiveFilePaths($sourceFolder . '/' . $file, $filenameToMatch, $returnList);
				if(is_array($subDirFiles) && !empty($subDirFiles))
				{
					foreach($subDirFiles as $subDirFilePath)
					{
						$filePaths[] = $subDirFilePath;
					}
				}
			}
		}
		closedir($dir_handle);
		if($returnList)
		{
			return $filePaths;
		} else {
			return true;
		}
	}
	//new function added for cropped listing assets deletion - end-20140128
}
class UploadProccessException extends Exception
{
	
}
?>